/* slabs memory allocation */
#ifndef SLABS_H
#define SLABS_H

#include <linux.h>



typedef struct {
    uint32_t size;      /* sizes of items */
    uint32_t perslab;   /* how many items per slab */

    void **slots;           /* list of item ptrs */
    uint32_t sl_total;  /* size of previous array */
    uint32_t sl_curr;   /* first free slot */

    void *end_page_ptr;         /* pointer to next free item at end of page, or 0 */
    uint32_t end_page_free; /* number of items remaining at end of last alloced page */

    uint32_t slabs;     /* how many slabs were allocated for this class */

    void **slab_list;       /* array of slab pointers */
    uint32_t list_size; /* size of prev array */

    uint32_t killing;  /* index+1 of dying slab, or zero if none */
    uint32_t requested; /* The number of requested bytes */
} slabclass_t;


/** Init the subsystem. 1st argument is the limit on no. of bytes to allocate,
    0 if no limit. 2nd argument is the growth factor; each slab will use a chunk
    size equal to the previous slab's chunk size times this factor.
    3rd argument specifies if the slab allocator should allocate all memory
    up front (if true), or allocate memory in chunks as it is needed (if false)
*/
void slabs_init(const size_t limit, const double factor, const bool prealloc);


/**
 * Given object size, return id to use when allocating/freeing memory for object
 * 0 means error: can't store such a large object
 */

unsigned int slabs_clsid(const size_t size);

/** Allocate object of given length. 0 on error */ /*@null@*/
void *slabs_alloc(const size_t size, unsigned int id);

/** Free previously allocated object */
void slabs_free(void *ptr, size_t size, unsigned int id);

/** Return a datum for stats in binary protocol */
bool get_stats(const char *stat_type, int nkey, ADD_STAT add_stats, void *c);

/** Fill buffer with stats */ /*@null@*/
void slabs_stats(ADD_STAT add_stats, void *c);

#endif
